from alembic.util import status
from flask_restful import Resource
from pycparser.ply.yacc import resultlimit

from Shopping.resources import user
from Shopping.resources.user.constants import SMS_CODE_EXPIRES
from comment.models import db
from comment.models.user import User
from flask import current_app, request, g

from comment.utils import const
from comment.utils.decorators import login_required
from comment.utils.sms_send import send_sms
import random
import json
from comment.utils.limiter import limiter as lmt
from Shopping.resources.user import constants
from flask_limiter.util import get_remote_address
from comment.utils.shopping_redis import redis_client
from flask_restful.reqparse import RequestParser
from comment.utils import parser
from comment.utils.tokens_itsdangerous import verify_tokens
from comment.utils.tokens_pyjwt import generate_tokens


# 定义的测试资源类
class Shopping_User(Resource):
    """
    在get函数上加上登录的拦截
    """
    method_decorators = {
        'get': [login_required],
        'post': [login_required]
    }
    def get(self): # 测试：当前get函数必须让用户登录之后才能访问，否则会报错
        current_app.logger.info('我的测试日志')
        # 这里的代码可能是会用到User模型类
        return {'hello':'get 测试'}
    def post(self):
        return {'hello':'post 测试'}
    def put(self):
        return {'hello':'put 测试'}

class User_SMS_Send(Resource):
    '''
    发送验证码的短信，
    '''
    error_message = '请一分钟过后再发送！！'
    decorators ={
    # 三个参数：
        # 参数1：限流的速率,参数2：key_func，参数3：如果超出限制之后的提示信息
        lmt.limit(constants.LIMIT_SMS_CODE_BY_MOBILE,
                  key_func=lambda :request.args['phone'],
                  error_message=error_message),
        lmt.limit(constants.LIMIT_SMS_CODE_BY_IP,
                  key_func=get_remote_address,
                  error_message=error_message)
    }
    def get(self):
        phone = request.args.get('phone').strip()
        code = const.generate_random_code()
        result = send_sms(phone,code)#返回的是接收的字符串
        # result 往里面添加手机号
        result['phone'] = phone

        # 短信发送成功之后，还需要把数据放到redis中，以便于下次验证,验证码的失效为5分钟
        redis_client.setex('shopping:code:{}'.format(phone),constants.SMS_CODE_EXPIRES,code)#参数1：key，参数2：过期时间，参数3：value

        return result

class AuthorizationCodeResource(Resource):
    '''
    提交手机号和验证码，开始验证
    '''
    def post(self):
        rp = RequestParser()
        rp.add_argument('phone',type=parser.mobile,required=True,help='请输入手机号')
        rp.add_argument('code',type=parser.regex(r'^\d{6}$'),required=True,help='请输入验证码')
        args = rp.parse_args()
        phone = args.phone
        code = args.code

        # 从redis数据库中得到之前保存的验证码
        key = 'shopping:code:{}'.format(phone)
        try:
            real_code = redis_client.get(key)#从redis中返回的事字节数据
        except Exception as e:
            current_app.logger.error(e)
            return {'message':'redis db 连接错误！！'},400
        #开始校验
        if not real_code or real_code.decode() != code:
            return {'message':'非法的验证码！'},500
        return {'phone':phone,'msg':'验证成功！！'}

class RegisterUserResource(Resource):

    """
    填写账户信息，完成用户的注册
    """
    def post(self):
        rp = RequestParser()
        rp.add_argument('phone',type=parser.mobile,required=True,help='请输入手机号')
        rp.add_argument('username',required=True)
        rp.add_argument('password',required=True)
        rp.add_argument('email',type=parser.email, required=True)
        args = rp.parse_args()
        username = args.username
        password = args.password
        phone = args.phone
        email = args.email

        #验证用户名是否唯一：先从MySQL数据库中根据当前用户名查询
        u = User.query.filter_by(username=username).first()
        if u:#用户名已存在
            current_app.logger.info('{}:用户名已存在，请换一个'.format(username))
            return {'msg':'用户名已存在！！'},400

        # 把用户信息保存到数据库
        u = User(username=username,phone=phone,pwd=password,email=email,status=0)
        db.session.add(u)
        db.session.commit()
        return {'msg':'注册成功！！'},200

class UserLoginResource(Resource):
    """
    用户登录
    """
    def post(self):
        username = request.form.get('username')
        password = request.form.get('password')

        if not all([username,password]):
            return {'message':'请输入用户名和密码！！'},402
        user = User.query.filter(User.username==username).first()
        if user:
            if user.check_password(password):
                # 必须把登录成功之后的用户ID得到token，token返回给前端
                token = generate_tokens(user.id)
                verify_tokens(token)
                return {'msg':'登录成功！！','token':token,'username':username},200
            else:
                return {'message':'密码错误！！'},400
        return {'message':'用户不存在！！'},402

class UserLoginOutResource(Resource):
    """
    用户登出
    """
    def post(self):
        if g.user_id:
            g.user_id = None
        return {'msg':'退出成功！！'},200

class IsExistPhoneResource(Resource):
    """
    判断手机号是否存在
    """
    def post(self):
        phone = request.form.get('phone')
        user = User.query.filter(User.phone==phone).first()
        if user:  #判断是否有该用户
            return {'isExist':True, 'message':'此手机号已注册！！','code': 203}
        return {'message':'手机号可以注册！！','code': 200}